package com.xhwl.centiotdata.suppliersystem.bailian;

import cn.hutool.core.collection.CollectionUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.xhwl.centiotdata.dao.ICampusUserStatisticsDao;
import com.xhwl.centiotdata.pojo.constant.BaiLianConstant;
import com.xhwl.centiotdata.service.cent.IBiCompanyCentService;
import com.xhwl.centiotdata.service.cent.IBiOperationSalesService;
import com.xhwl.centiotdata.utils.ThreadPoolUtils;
import com.xhwl.common.pojo.statistics.DwdFactOperationSaleRecord;
import com.xhwl.common.pojo.statistics.OdsOperationSale;
import com.xhwl.common.utils.CalendarUtil;
import com.xhwl.common.utils.StringUtils;
import com.xhwl.common.vo.cent.statistics.SaleThirdDataVO;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.math.BigDecimal;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.concurrent.CompletableFuture;
import java.util.stream.Collectors;

/**
 * @Author： lianghz
 * @Description：
 * @Date 2021/09/20/ 10:09
 */
@Service
public class SaleBaiLianHandler {

    private static final Logger log = LoggerFactory.getLogger(SaleBaiLianHandler.class);

    @Autowired
    private GeneralBaiLianHandler generalBaiLianHandler;

    @Autowired
    private IBiCompanyCentService companyCentService;

    @Autowired
    ICampusUserStatisticsDao iCampusUserStatisticsDao;

    @Autowired
    IBiOperationSalesService iBiOperationSalesService;

    /**
     * 接入层是 xxl-job 定点10分钟执行一次 00:00的时候需要统计前一天的数值
     * <p>
     * <p>
     * 当日获取不到租赁的销售额，只有次日才能查询到租赁的销售额
     * time为null，获取当日
     */
    private String getUrlData(String ipAndPort, String time) {
        HashMap<String, Object> params = Maps.newHashMap();
        if (StringUtils.isNotEmpty(time)) {
            params.put("date", time);
        }
        JSONObject resultObject = generalBaiLianHandler.post(ipAndPort + BaiLianConstant.SALES_URL, params);
        String data = resultObject.getString("data");
        if (StringUtils.isEmpty(data)) {
            log.error("post path:{};params:{}; data is null !", ipAndPort + BaiLianConstant.SALES_URL, JSON.toJSONString(params));
            return null;
        }
        return data;
    }


    /**
     * 每小时调用一次(弃用)
     *
     * @param projectId
     * @param ipAndPort
     */
    @Deprecated
    public void pullSale(Integer projectId, String ipAndPort) {
        String data = getUrlData(ipAndPort, null);
        List<SaleThirdDataVO> records = JSONObject.parseArray(data, SaleThirdDataVO.class);
        Date nowTime = new Date();
        //可能存在店铺相同的情况,需要把数据进行累加
        List<OdsOperationSale> saleList = records.stream().map(item -> {
            OdsOperationSale odsOperationSale = new OdsOperationSale();
            odsOperationSale.setProjectId(projectId);
            odsOperationSale.setCreatedAt(nowTime);
            odsOperationSale.setShopId(item.getDepartmentID());
            odsOperationSale.setSalesType(Integer.valueOf(item.getSalesType()));
            item.setSales(item.getSales());
            item.setCount(item.getCount());
            odsOperationSale.setSales(item.getSales());
            odsOperationSale.setCount(item.getCount());

            return odsOperationSale;
        }).collect(Collectors.toList());
        //发送业务逻辑
        if (CollectionUtil.isNotEmpty(saleList)) {
            log.info("XXXXXXXX销售总条数：{}", saleList.size());
            List<List<OdsOperationSale>> pList = Lists.partition(saleList, 200);
            List<CompletableFuture> futureList = Lists.newArrayList();
            for (List<OdsOperationSale> vos : pList) {
                log.info("XXXXXXXX每次执行的总数量：{}", vos.size());
                CompletableFuture cf = CompletableFuture.runAsync(() -> companyCentService.asyncSaleInfo(vos), ThreadPoolUtils.executor);
                futureList.add(cf);
            }
            CompletableFuture.allOf((futureList.toArray(new CompletableFuture[]{}))).join();
        }
    }


    /**
     * 拉取昨日营销数据并同步，租赁数据只有第二天才可以拉取到，所以过了晚上12点拉取同步一次
     */
    public void pullSalesYesterday(Integer projectId, String ipAndPort) {
        pullSales(projectId, ipAndPort, getYesterdayDate());
    }

    /**
     * 同步当日数据，每小时一次，新的数据会覆盖旧的数据
     *
     * @param projectId
     * @param ipAndPort
     */
    public void pullSalesToday(Integer projectId, String ipAndPort) {
        pullSales(projectId, ipAndPort, null);
    }


    /**
     * 拉取前面多少天的数据
     */
    public void pullSalesDays(Integer projectId, String ipAndPort, int day) {
        String[] dayEnums = CalendarUtil.getDayEnums(CalendarUtil.DATE_FORMAT[1], day);
        for (int i = 0; i < dayEnums.length; i++) {
            pullSales(projectId, ipAndPort, dayEnums[i]);
        }
    }

    /**
     * 获取并同步经营数据
     *
     * @param projectId
     * @param ipAndPort
     * @param date
     * @param isMock    是否是模拟数据
     * @return errorMsg，null代表无异常
     */
    public String pullSalesReturnError(Integer projectId, String ipAndPort, String date, boolean isMock) {
        String finalTime = StringUtils.isEmpty(date) ? getTodayDate() : date;
        String data = isMock ? BaiLianMockUtil.mockSaleData(finalTime) : getUrlData(ipAndPort, date);
        if (StringUtils.isEmpty(data)) {
            return "获取三方经营数据异常";
        }
        List<DwdFactOperationSaleRecord> list = parseResult(data, finalTime, projectId);
        try {
            iBiOperationSalesService.asyncRecord(list);
        } catch (Exception e) {
            e.printStackTrace();
            return "同步bi异常";
        }
        return null;
    }

    /**
     * 同步销售数据，如果date为空，同步当日数据
     *
     * @param projectId
     * @param ipAndPort
     * @param date      不为null，同步指定日期。null，同步当日
     */
    public void pullSales(Integer projectId, String ipAndPort, String date) {
        String finalTime = StringUtils.isEmpty(date) ? getTodayDate() : date;
        String data = getUrlData(ipAndPort, date);
        List<DwdFactOperationSaleRecord> list = parseResult(data, finalTime, projectId);
        iBiOperationSalesService.asyncRecord(list);
    }

    private List<DwdFactOperationSaleRecord> parseResult(String result, String date, Integer projectId) {
        List<SaleThirdDataVO> records = JSONObject.parseArray(result, SaleThirdDataVO.class);
        Date eventTime = formatPreciseTime(date);
        String[] ss = date.split("-");
        List<DwdFactOperationSaleRecord> list = new ArrayList<>();
        for (SaleThirdDataVO record : records) {
            List<SaleThirdDataVO.RankObj> salesRank = record.getSalesRank();
            //如果有销售员信息，就拆分数据成多条数据
            if (!CollectionUtils.isEmpty(salesRank)) {
                for (SaleThirdDataVO.RankObj rankObj : salesRank) {
                    DwdFactOperationSaleRecord saleRecord = generateRecord(projectId, ss, eventTime, record, rankObj);
                    list.add(saleRecord);
                }
            } else {
                DwdFactOperationSaleRecord saleRecord = generateRecord(projectId, ss, eventTime, record, null);
                list.add(saleRecord);
            }
        }
        return list;
    }

    private DwdFactOperationSaleRecord generateRecord(Integer projectId, String[] times, Date eventTime, SaleThirdDataVO record, SaleThirdDataVO.RankObj rankObj) {
        DwdFactOperationSaleRecord saleRecord = new DwdFactOperationSaleRecord();
        saleRecord.setProjectId(projectId);
        saleRecord.setYear(times[0]);
        saleRecord.setMonth(times[1]);
        saleRecord.setDay(times[2]);
        BigDecimal sales = rankObj != null ? rankObj.getSales() : record.getSales();
        saleRecord.setValue(sales);
        saleRecord.setCurrentValue(sales);
        saleRecord.setPrevValue(new BigDecimal(0));
        BigDecimal count = rankObj != null ? rankObj.getCount() : record.getCount();
        saleRecord.setCount(count);
        saleRecord.setCurrentCount(count);
        saleRecord.setPrevCount(new BigDecimal(0));
        saleRecord.setSalesType(Integer.valueOf(record.getSalesType()));
        saleRecord.setShopId(record.getDepartmentID());
        Map<String, Object> shopInfo = iCampusUserStatisticsDao.findShop(record.getDepartmentID());
        saleRecord.setShopName(shopInfo != null ? (String) shopInfo.get("name") : null);
        saleRecord.setShopType(shopInfo != null ? (Integer) shopInfo.get("type") : null);
        //赋值供应货物品类
        saleRecord.setSupplierCategoryCode(shopInfo != null ? (String) shopInfo.get("supplier_category_code") : null);
        //赋值销售员信息
        if (rankObj != null) {
            saleRecord.setSellerNo(rankObj.getNo());
            saleRecord.setSellerName(rankObj.getName());
        }
        saleRecord.setEventTime(eventTime);
        saleRecord.setCreatedAt(new Date());
        return saleRecord;
    }

    /**
     * 获取昨天的date
     *
     * @return yyyy-MM-dd
     */
    private static String getYesterdayDate() {
        Date nowTime = new Date();
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        Calendar c = Calendar.getInstance();
        c.setTime(nowTime);
        c.add(Calendar.DAY_OF_MONTH, -1);
        String yesterday = sdf.format(c.getTime());
        return yesterday;
    }

    /**
     * 获取今天的date
     *
     * @return yyyy-MM-dd
     */
    private static String getTodayDate() {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        return sdf.format(new Date());
    }

    /**
     * @param date yyyy-MM-dd
     * @return 当天的23点的date
     */
    private static Date formatPreciseTime(String date) {
        String eventEndTime = date + " 23:00:00";
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        Date eventTime = null;
        try {
            eventTime = sdf.parse(eventEndTime);
        } catch (ParseException e) {
            e.printStackTrace();
        }
        return eventTime;
    }

}
